var incimg;
var pictures;
var currentimg = 0;     //eventually store this in the options so it doesn't
              // start at 0 every time
var timer_slideshow;
var timer_notifications;
var loggedin = false;

options.putDefaultValue( "session_key", "" );
options.putDefaultValue( "ss_timer", 5000 ); // used for slideshow timer

function main()
{
  bottom.height = navbar.height + notifications.height;
  //give the user something to see while they're waiting
  resize();

  //start the login process by getting an auth token
  get_auth_token();

/*
*****we need a way to figure out if the user should have to log in or not... ie, if they've
  used the program before, if it's the same user? can we just assume this?

*****also need to get a timer going for the notifications to refresh...

  if( options.getValue( "session_key" ) == "" )
    get_auth_token();
  else
  {
    //get session info
    //start getting picture
    session_key = options.getValue( "session_key" );
  }

  //this is just here so it clears it now and then... have to figure out when it needs to be reset
  //  like if users change or something? or could just have a 'logout' button in options that does it
  options.putValue( "session_key", "" );
*/

}

/* start_slideshow()
  Starts the slideshow timer and then calls slideshow to display a picture
 */
function start_slideshow()
{
  //start timer
  var temptimer = options.getValue( "ss_timer" );
  timer_slideshow = view.setInterval( slideshow, temptimer );

  //show pic
  slideshow();
}

/* stop_slideshow()
  Stops the slideshow
*/
function stop_slideshow()
{
  //stop the timer for the slideshow
  view.clearInterval( timer_slideshow );
}

// advances to the next photo
function next_photo()
{
  stop_slideshow();

  if( currentimg == pictures.length )
    currentimg = 0;
  else
    currentimg = currentimg + 1;

  start_slideshow();
}

// backtracks to the previous photo
function prev_photo()
{
  stop_slideshow();

  if( currentimg < 2 )
  {
    currentimg = pictures.length - 1;
  }
  else
  {
    currentimg = currentimg - 2;
  }

  start_slideshow();
}

// Goes to first photo of show
function first_photo()
{
  stop_slideshow();
  currentimg = 0;
  start_slideshow();
}

// Goes to last photo of show
function last_photo()
{
  stop_slideshow();
  currentimg = pictures.length - 1;
  start_slideshow();
}

/* slideshow()
  Displays the next picture in the pictures array
post-condition:
  currentimg has increased by 1
 */
function slideshow()
{
  incimg = new XMLHttpRequest();
  incimg.onreadystatechange = receive_pic;

  //make sure we won't step over the bounds
  if( currentimg == pictures.length )
    currentimg = 0;

  //get the image
  incimg.open( "GET", pictures[currentimg].src_big, true );
  incimg.send();

  currentimg++;
}

/* receive_pic()
  Handler function for retreiving pictures.  Waits until the pic is received
  and then puts it as the facebook picture's source in the slideshow
 */
function receive_pic()
{
  //readyState is 4 after the request is finished, so..
  if( incimg.readyState == 4 )
  {
    //have the pic, put it as the source
    fbpic.src = incimg.responseStream;

    resize();
  }
}

/* resize()
  Resizes the picture and keeps the aspect ratio so that both it and the
  bottom bar fit properly inside the widget's space.  It centers everything
  horizontally and vertically
 */
function resize()
{
  //multiplier used with resizing the picture
  var x;

  //check the ratio of picture dimensions to view dimensions, the smallest
  //  is the one we need to resize have to take into consideration the navbar
  //  and notifications bar
  if((fbpic.srcheight / (view.height - bottom.height))
                      < (fbpic.srcwidth / view.width ))
    x = view.width / fbpic.srcwidth;
  else
    x = (view.height - bottom.height) / fbpic.srcheight;

  //resize picture and navbar to match the picture length
  fbpic.height  = fbpic.srcheight * x;
  fbpic.width   = fbpic.srcwidth * x;

  //fix the notifications and navbar to be at the bottom of the view window
  //bottom.y = (view.height - bottom.height);

  // make it so it's centered vertically... want the same amt of space above
  //  and below the combined pic and bottom part
  bottom.y = 0.5 * (view.height - (fbpic.height + bottom.height)) + fbpic.height;
  fbpic.y = 0.5 * (view.height - (fbpic.height + bottom.height));


  //don't let bottom.width get less than 220 or it distorts text underneath
  if( fbpic.width < 220 )
    bottom.width = 220;
  else
    bottom.width = fbpic.width;

  //need to center the pic on the bottom...


  //center the picture horizontally and place it above the navbar and
  //  notifications area
  fbpic.x = .5 * (view.width - fbpic.width);

  //need to center the navbar....
  bottom.x = .5 * (view.width- bottom.width)

  //set the backdrop, it's used for vertical pictures so there's something
  //flush with the bottom bar
  picbackdrop.y = fbpic.y;
  picbackdrop.height = fbpic.height;
  picbackdrop.x = bottom.x;
  picbackdrop.width = bottom.width;

  //resize the notifications
  notifications_resize();
}


/* notifications_resize()
  Resizes the notifications area so the friend request info is flush left
  with the bottom div and the events info is 50% across the bottom div
 */
function notifications_resize()
{
  //put the friend requests flush on the left side
  notify_num_friends.x = notify_pic_friends.srcwidth;
  notify_friends_text.x = notify_num_friends.x + 10;


  //put the event requests halfway across
  notify_pic_events.x = (1/2) * bottom.width;
  notify_num_events.x = (1/2 * bottom.width) + notify_pic_events.srcwidth + 5;
  notify_events_text.x = notify_num_events.x + 10;
}

/* expandImg()
  This function retrieves all of the information about the photo and creates
  a new window to display a bigger copy of the photo + photo information
 */
function expandImg()
{
  var query = new Array();
  query.push( "api_key=" + api_key );
  query.push( "session_key=" + session_key );
  query.push( "call_id=" + get_call_id( new Date() ) );
  query.push( "v=" + v );
  query.push( "format=" + format );
  query.push( "method=facebook.users.getInfo" );
  query.push( "uids=" + pictures[currentimg-1].owner );
  query.push( "fields=first_name,last_name" );
  query.sort();
  query.push( "sig=" + get_sig( query ) );

  fb_query( query.join( "&" ), restserver, function()
  {
    if( xml_request.readystate == 4 )
    {
      //get the response and parse it with eval
      var response = xml_request.responseText;
      userinfo = eval( "(" + response + ")" );
      stop_slideshow();

      // Create the window to display the new information
      var HTML_STUFFZ = "<html>" +
      "<body>" +
      "<img src=\"" + pictures[currentimg-1].src_big + "\" alt=\"Facebook Photo\" /><br />" +
      "Caption: " + pictures[currentimg-1].caption +
      "<br />Owner: " + userinfo[0].first_name + " " + userinfo[0].last_name +
      "<br />Link: " + pictures[currentimg-1].link +
      "</body>" +
      "</html>";

      // Create the details view and set its content. Specifying 'undefined' in
      // setContent makes it such that no time is displayed in the details view
      var htmlDetailsView = new DetailsView();
      htmlDetailsView.html_content = true;
      htmlDetailsView.setContent("", undefined, HTML_STUFFZ, false, 0);


      // In order to have two way communication with the HTML details view, we
      // need to set an external object that can receive events. This is called
      // from the HTML using the javascript "window.external.onItemClick(text);".
      var externalObject = new Object();
      externalObject.onItemClick = onItemClick;
      htmlDetailsView.external = externalObject;

      // Show the details view
      pluginHelper.showDetailsView(htmlDetailsView, "Facebook Photo", gddDetailsViewFlagToolbarOpen, onDetailsViewFeedback);

      // Restart the slideshow
      start_slideshow();
    }
  } );
}

// This function catches when the user changes the slideshow timer
function onOptionChanged() {
  // optionChanged will contain the name of the option which was changed
  var optionChanged = event.propertyName;

  // Update only the appropriate checkbox
  if (optionChanged == "ss_timer")
  {
    stop_slideshow();
    start_slideshow();
  }
}

function onItemClick(text)
{
  // Display which item was clicked on
  view.alert(text);

  // Close the details view
  pluginHelper.CloseDetailsView();
}

function onDetailsViewFeedback(detailsViewFlags) {
  if (detailsViewFlags == gddDetailsViewFlagNone) {
    // User closed the details view
  } else if (detailsViewFlags == gddDetailsViewFlagToolbarOpen) {
    // User clicked on the title of the details view
  }
}

/*

    FB API TEST

    USING REST SERVER

    part of authentication (the first part) is to generate an auth token

 */
var xml_request;

var restserver = "http://api.facebook.com/restserver.php";

var api_key   = "f817209f64786a922cfdac483a1ea257";
var secret_key  = "e90df32a7231cd47b82a611a11beaccf";
var v       = "1.0";
var format    = "JSON";

var auth_token;
var session_key;
var userid;

/* login
  To login we must first get an authtoken from Facebook since it's a desktop
  app.  Then we have to open the login page and then proceed to get new
  session info
 */
function get_auth_token()
{
  var query = new Array();

  //first we need to generate an auth token to have the user login.  it
  //  requires the api key, v, format, and sig
  query.push( "api_key=" + api_key );
  query.push( "v=" + v );
  query.push( "format=" + format );
  query.push( "method=facebook.auth.createToken" );

  //sort and get the signature by calling get_sig
  query.sort();
  query.push( "sig=" + get_sig( query ) );

  //query the auth.getToken
  fb_query( query.join( "&" ), restserver, function()
  {
    //readystate = 4 when it's finished and loaded
    if( xml_request.readystate == 4 )
    {
      //need to get the auth token
      var response = xml_request.responseText;

      auth_token = eval( "(" + response + ")" );
      gadget.debug.trace( "response to authToken = " + response );

      //we have the auth token, now must open up a browser to login
      var winShell = new ActiveXObject("Shell.Application");
      var loginURL = new Array();
      winShell.ShellExecute( "https://login.facebook.com/login.php?api_key=" + api_key + "&v=" + v + "&auth_token=" + auth_token );

      //have a 'you are not logged in, please log in and then click OK to continue'
      login.visible = true;
      login_text.enabled = true;
    }
  } );
}


/* get_session()
  Gets the facebook session from the user logging in.  Required for the api
  calls.
post-condition:
  Facebook API calls can be made by using "session_key" as the session_key
  variable in the API call.  The variable userid also contains the ID of the
  session's user.
 */
function get_session()
{
  //make the "click here when logged in" disappear
  login.visible = false;
  login_text.enabled = false;

  var query = new Array();
  query.push( "api_key=" + api_key );
  query.push( "v=" + v );
  query.push( "method=facebook.auth.getSession" );
  query.push( "auth_token=" + auth_token );
  query.push( "format=" + format );
  query.sort();
  query.push( "sig=" + get_sig( query ) );

  fb_query( query.join( "&" ), restserver, function()
  {
    if( xml_request.readystate == 4 )
    {
      //get the response and parse it with eval
      var response = xml_request.responseText;
      session = eval( "(" + response + ")" );

      //if the session is set to 0 - never expires - then store it in our
      //  options to prevent further logins
      if( !session.expires )
        options.putValue( "session_key", session.session_key );

      session_key = session.session_key;

      userid = session.uid;
      loggedin = true;

      //we now have a valid session, time to get our stuff
      view.setInterval( get_notifications, 60000 * 10 );
      get_notifications();
      get_users_pictures();
    }
  } );
}



/*get_users_pictures
  Retrieves the array of the user's photos on facebook
post-condition:
  The logged in user's pictures can be found in the array pictures[]
 */
function get_users_pictures()
{
  var query = new Array();
  query.push( "api_key=" + api_key );
  query.push( "session_key=" + session_key );
  query.push( "call_id=" + get_call_id( new Date() ) );
  query.push( "v=" + v );
  query.push( "format=" + format );
  query.push( "method=facebook.photos.get" );
  query.push( "subj_id=" + userid );
  query.sort();
  query.push( "sig=" + get_sig( query ) );

  fb_query( query.join( "&" ), restserver, function()
  {
    //wait for request to finish sending back information
    if( xml_request.readystate == 4 )
    {
      var response = xml_request.responseText;

      pictures = eval( "(" + response + ")" );

      //if the user has pictures, start the slideshow
      if( pictures.length != 0 )
        start_slideshow();
      else
        view.alert( "you have no pictures!" );
    }
  } );
}




/* get_notifications()
  Gets the users friend and event invites
post-condition:
  notify_num_events's text contains the number of event invites
  notify_num_friends's text contains the # of friend invites
*/
function get_notifications()
{
  var query = new Array();

  query.push( "api_key=" + api_key );
  query.push( "session_key=" + session_key );
  query.push( "call_id=" + get_call_id( new Date() ) );
  query.push( "v=" + v );
  query.push( "method=facebook.notifications.get" );
  query.push( "format=" + format );
  query.sort();
  query.push( "sig=" + get_sig( query ) );

  fb_query( query.join( "&" ), restserver, function()
  {
  //  view.alert( "wtf? status = " + xml_request.status );
    //view.alert( xml_request.readyState );
    if( xml_request.readystate == 4 )
    {
      var notif_response = xml_request.responseText;

      var notifications = eval( "(" + notif_response + ")" );

      if( notifications.event_invites.length )
        notify_num_events.innerText = notifications.event_invites.length;
      else
        notify_num_events.innerText = 0;

      if( notifications.friend_requests.length )
        notify_num_friends.innerText = notifications.friend_requests.length;
      else
        notify_num_friends.innerText = 0;

      //ew.alert( "event_invites = " + notifications.event_invites.length );
    }

  } );
}


/* fb_query
  query: the constructed query
  url: url of where to send the query
  handler: whenever there's a state change in the XMLHttpRequest the function is called
 */
function fb_query( query, url, handler )
{
  xml_request = new XMLHttpRequest();

  //when the state changes, call the 'handler' function
  xml_request.onreadystatechange = handler;

  try
  {
    gadget.debug.trace( "fb_query with query = " + query );

    xml_request.open( "POST", restserver );
    xml_request.setRequestHeader( "Content-Type", "application/x-www-form-urlencoded" );
    xml_request.send( query );
  }catch (e)
  {
    //gadget.debug.error( "error in sending REST request... " + e );
    view.alert( "error in sending REST request... " + e );
  }

}

function get_sig( query )
{
  return hex_md5( query.join('') + secret_key );
}

function get_call_id( date )
{
  return date.getTime();
}